HtmlTable = Class.refactor(HtmlTable, {
	options: {
		sortable: true,
		selectable: true,
		editable: true,
		classEditableCell: 'editable',
		classReadOnlyCell: 'readonlycell'
	},
	
	initialize: function() {
		this.previous.apply(this, arguments);
		if (this.occluded) return this.occluded;
	},
	
	push: function() {
		var pushed = this.previous.apply(this, arguments),
			instanceRef = this;
		// Add editable class and event to all non-header cells
		if (pushed.tr.parentNode.tagName.toUpperCase() != 'THEAD') {
			pushed.tds.each(function(data) {
				if (!data.hasClass(this.options.classReadOnlyCell)) {
					data.addClass(this.options.classEditableCell);
					data.addEvents({ 'dblclick': function(event) { 				
							/*
								For a double click:
									Firefox fires Click, Click, DblClick
									IE fires Click, DblClick
								
								In the context of the selectable rows in our table, this means that firefox toggles the selection twice,
								returning it to its original state, and then fires the dblclick event. However, IE only toggles the selection once,
								changing its selected state before firing the dblclick event. If the row that was double clicked was selected, this 
								causes the beginEdit method to deselect all of the selected rows. If that row was not selected, it becomes selected.
								
								In IE we always have to toggle the row once more.
							*/
							if (Browser.Engine.trident) {
								var row = event.target.getParent(),
									klass = this.options.classRowSelected;
								if (row.hasClass(klass))
									row.removeClass(klass);
								else
									row.addClass(klass);
							}
							this.beginEdit(event); 
						}.bind(this)
					});
				}
			}, this);
		}
		return pushed;
	},
	focusRow: function() {
		var row = arguments[1] || arguments[0],
			inputs = row.getElements('input');
			
		// Hacky... add more types here to ignore focus changes
		if (inputs.some(function(item) { return item.type == "checkbox" || item.type == "select" || item.type == "radio" })) 
			return false;
			
		this.previous.apply(this, arguments);
	},
	beginEdit: function(event) {		
		var el = event.target,
			before = el.get('html').trim(),
			displayBefore = before == "&nbsp;" ? "" : before,
			input = null;

		if (el.hasClass('buttons'))
			return;
		
		// Deselect selected rows if user edits an unselected row.
		if(!el.getParent().hasClass('table-tr-selected')) {
			var selected = $$('.table-tr-selected');
			if (selected && selected.length > 0) {
				selected.each(function(element) {
					element.removeClass('table-tr-selected');
				});
			}
		}
		
		el.set('html','');
		//replace current text/content with input or textarea element
		if(el.hasClass('textarea')) {
			input = sharplib.fieldMakers['textarea'].makeField('', displayBefore);
			//var input = new Element('textarea', { 'class':'box', 'text': displayBefore });
		} else if(el.hasClass('text')) {
			input = sharplib.fieldMakers['text'].makeField('', displayBefore);
			input.addEvent('keydown', function(e) { 
				if(e.key == 'enter') { 
					this.fireEvent('blur'); 
				}
			});
			// var input = new Element('input', { 'class':'box', 'value': displayBefore });
		} else if(el.hasClass('checkbox')) {
			input = sharplib.fieldMakers['checkbox'].makeField('', displayBefore);
		} else if(el.hasClass('select') || el.hasClass('radio')) {
			/*
				Radio button lists and single selects are different metaphors for the same task.
				Select lists are easy(ish) to do in the editable table. Radio buttons are driving me
				batty. Simplifying by treating radio button lists as single selects.
			*/
			input = sharplib.fieldMakers['select'].makeField('', displayBefore, this.options.providers[el.get('providerid')]);
		} else if(el.hasClass('multiselect')) {
			input = sharplib.fieldMakers['multiselect'].makeField('', displayBefore, this.options.providers[el.get('providerid')]);
		}
		
		input.inject(el)
		if (input.select)
			input.select();
		input.focus();
		input.addEvent('blur', function() { this.endEdit(el, input, before); }.bind(this));
	},
	
	endEdit: function(element, input, initialValue) {
		function record(store, element, newValue, oldValue) {
			var row = element.getParent().tagName == "TD" ? element.getParent().getParent() : element.getParent(),
				targetElement = element.tagName == "INPUT" ? element.getParent() : element;
				
			
			newValue == "&nbsp;" ? targetElement.set('html', newValue) : targetElement.set('text',newValue)
			targetElement.addClass(newValue != '' ? '' : 'editable-empty');
			
			if (newValue != oldValue) {	
				row.addClass('dirty');
				
				if (store)
					store.notify(targetElement);
			}
		}

		var row = element.getParent(),
			val = '',
			tag = element.getAttribute('itemTag'),
			targetClass = tag.slice(tag.lastIndexOf(':')+1),
			selected = $$('.table-tr-selected td.' + targetClass);
		
		if(!input.get) {
			val = input.trim()
		} else if(input.type == "checkbox") {
			val = input.checked.toString();
		} else {
			val = input.get('value').trim();
		}
		
		if (val == '')
			val = "&nbsp;";
		
		if (selected && selected.length > 0) {
			selected.each(function(el) {
				record(this.options.store, el, val, initialValue);
			}, this);
		} else {
			record(this.options.store, element, val, initialValue);
		}
	}
});